# turtle_tracks.py

from __future__ import print_function

from itertools import takewhile

def run(filename):
    with open(filename, 'rt') as f:
        init(int(f.readline()))
        blank_line = f.readline()
        if blank_line.strip():
            raise SyntaxError("Expected blank line",
                              (filename, 2, 1, blank_line))
        run_tokens(tokenize_file(filename, f))
    draw_board()

def tokenize_file(filename, f):
    for lineno, line in enumerate(f, 3):
        yield from tokenize_line(filename, lineno, line)
    # yield EOF token (None)
    yield None, (filename, lineno, 0, None)

def tokenize_line(filename, lineno, line):
    r'''Tokenize one line from the input file.

        >>> for t, fp in tokenize_line('filename', 22, 'FD 33'):
        ...     print(repr(t), fp)
        'FD' ('filename', 22, 1, 'FD 33')
        33 ('filename', 22, 4, 'FD 33')

        >>> for t, fp in tokenize_line('filename', 44, 'A [B] C'):
        ...     print(repr(t), fp)
        'A' ('filename', 44, 1, 'A [B] C')
        '[' ('filename', 44, 3, 'A [B] C')
        'B' ('filename', 44, 4, 'A [B] C')
        ']' ('filename', 44, 5, 'A [B] C')
        'C' ('filename', 44, 7, 'A [B] C')
    '''
    offset = 1
    rest = line.rstrip()
    while rest:
        offset += leading_spaces(rest)
        rest = rest.strip()
        sp = rest.find(' ')
        if sp == -1:
            t = rest
            rest = ''
        else:
            t = rest[:sp]
            rest = rest[sp:]
        if t[0] == '[':
            yield '[', (filename, lineno, offset, line)
            offset += 1
            t = t[1:]
            if not t: continue
        if t[-1] == ']':
            t = t[:-1]
            do_bracket = True
        else:
            do_bracket = False
        if t:
            try:
                yield int(t), (filename, lineno, offset, line)
            except ValueError:
                yield t, (filename, lineno, offset, line)
            offset += len(t)
        if do_bracket:
            yield ']', (filename, lineno, offset, line)
            offset += 1

def run_tokens(tokens):
    r'''Runs commands from tokens.
    '''
    tokens = iter(tokens)
    for command, file_location in tokens:
        if command not in Commands:
            if command is None:
                # EOF token, we're done!
                return
            raise SyntaxError("Illegal command: {}".format(command),
                              file_location)
        Commands[command](tokens)
    raise SyntaxError("Premature EOF")

def leading_spaces(line):
    r'''Returns the number of leading spaces on `line`.

        >>> leading_spaces('  XYZ')
        2
        >>> leading_spaces('XYZ')
        0
        >>> leading_spaces('')
        0
    '''
    return len(line) - len(line.lstrip())

def repeat(tokens):
    r'''Process the REPEAT command.
    '''
    n = get_int(tokens)
    t, file_location = next(tokens)
    if t != '[':
        raise SyntaxError("Expected '['", file_location)
    last_token = last_file_location = None
    def not_open_bracket(token):
        nonlocal last_token, last_file_location
        last_token, last_file_location = token
        return last_token != ']' and last_token is not None
    command_tokens = list(takewhile(not_open_bracket, tokens))
    if last_token != ']':
        raise SyntaxError("Missing ']'", last_file_location)
    command_tokens.append((None, last_file_location))
    for _ in range(n):
        run_tokens(command_tokens)

def init(size):
    r'''Initialize the Board to `size`.

        >>> import turtle_tracks
        >>> turtle_tracks.init(22)
        >>> len(turtle_tracks.Board)
        22
        >>> len(turtle_tracks.Board[0])
        22
    '''
    global Size, Board, Position, Direction
    Size = size
    Board = [[False] * size for i in range(size)]
    Position = (size // 2,) * 2
    Board[Position[0]][Position[1]] = True
    Direction = 0, -1

def move(distance):
    r'''Move `distance`.

    This uses the global variable Direction for the x_inc and y_inc.

        >>> import turtle_tracks
        >>> turtle_tracks.init(21)
        >>> turtle_tracks.Position
        (10, 10)
        >>> turtle_tracks.move(5)
        >>> turtle_tracks.Position
        (10, 5)
        >>> turtle_tracks.move(-5)
        >>> turtle_tracks.Position
        (10, 10)
    '''
    global Position
    sign = 1 if distance > 0 else -1
    x, y = Position
    for _ in range(abs(distance)):
        x += sign * Direction[0]
        y += sign * Direction[1]
        Board[y][x] = True      # x indexes inner list
    Position = x, y

Directions = [
  # (x_inc, y_inc) degrees (0 == up)
    (0, -1),     #    0
    (1, -1),     #   45
    (1, 0),      #   90
    (1, 1),      #  135
    (0, 1),      #  180
    (-1, 1),     #  225
    (-1, 0),     #  270
    (-1, -1),    #  315
]
  
def turn(degrees):
    r'''Turns `degrees`.

        >>> import turtle_tracks
        >>> turtle_tracks.init(21)
        >>> turtle_tracks.Direction
        (0, -1)
        >>> turtle_tracks.turn(270)
        >>> turtle_tracks.Direction
        (-1, 0)
        >>> turtle_tracks.turn(-270)
        >>> turtle_tracks.Direction
        (0, -1)
        >>> turtle_tracks.turn(-270)
        >>> turtle_tracks.Direction
        (1, 0)
    '''
    global Direction
    Direction = Directions[(Directions.index(Direction) + degrees // 45) % 8]

def get_int(tokens):
    ans, file_location = next(tokens)
    if not isinstance(ans, int):
        raise SyntaxError("Expected an integer", file_location)
    return ans

def draw_board():
    r'''Draws the board.

    Which is stored in the global variable `Board`.

        >>> import turtle_tracks
        >>> turtle_tracks.init(3)
        >>> turtle_tracks.draw_board()
        . . .
        . X .
        . . .
    '''
    for row in Board:
        print(' '.join('X' if mark else '.' for mark in row))

Commands = {
    'FD': lambda tokens: move(get_int(tokens)),
    'BK': lambda tokens: move(-get_int(tokens)),
    'RT': lambda tokens: turn(get_int(tokens)),
    'LT': lambda tokens: turn(-get_int(tokens)),
    'REPEAT': repeat,
}

if __name__ == "__main__":
    import sys

    if len(sys.argv) != 2:
        print("usage: turtle_tracks.py command_file", file=sys.stderr)
        sys.exit(2)

    run(sys.argv[1])
